package com.ling.module1sbbyyds.service.news.usercenter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ling.sbbyyds.entity.community.CommunityPosts;
import com.ling.sbbyyds.entity.exception.ApiWarningInfoException;
import com.ling.sbbyyds.entity.users.User;
import com.ling.sbbyyds.interaction.vo.OtherUser;
import com.ling.sbbyyds.interaction.vo.UserInfoVo;
import com.ling.module1sbbyyds.utils.*;
import com.ling.sbbyyds.common.PageUtils;
import com.ling.sbbyyds.imagetools.ImageUtils;
import com.ling.sbbyyds.interaction.ResultVo;
import com.ling.sbbyyds.mapper.community.CommunityPostsMapper;
import com.ling.sbbyyds.mapper.user.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * 天道酬勤、学无止境
 *
 * @Description: 类描述
 * @author: ling
 * @date: 2022年03月26日
 */
@Service
@Slf4j
public class UserService {

    @Autowired(required = false)
    private UserMapper userMapper;
    @Autowired(required = false)
    private CommunityPostsMapper communityPostsMapper;
    @Autowired(required = false)
    private ValidateCode validateCode;
    @Autowired
    private FileLocalStorageTool fileLocalStorageTool;
    @Autowired
    private RedisTemplate<String, String> redis;
    @Autowired
    private RedisDataUtil redisDataUtil;

    /**
     * 用户头像图片存放目录
     */
    public static String USER_IMAGE_PATH = "userimage";

    /**
     * @param file:
     * @Description: 上传头像
     * @author: ling
     * @date: 2022/5/8
     */
    public ResultVo uploadImageImpl(MultipartFile file, HttpServletRequest request) throws IOException {

        //头像路径
        String userAvatarPath;
        if (!file.isEmpty()) {
            //  上传图片到服务器
            userAvatarPath = fileLocalStorageTool.uploadImage(USER_IMAGE_PATH, 1, file);
            //获取用户操作用户
            Map<String, Object> userData = UserThreadLocal.get();
            User user = (User) userData.get("user");
            //保存用户信息
            User userInfo = new User()
                    .setId(user.getId())
                    .setAvatar(userAvatarPath);
            //更改用户头像
            userMapper.updateByPrimaryKeySelective(userInfo);
            resetRedisUserInfo(request.getHeader("AuthorizationOauth_Token"));
            //修改redis中得内容
            return ResultVo.success(true);
        }
        return ResultVo.fail("上传图片失败！");
    }

    /**
     * 更新用户信息
     *
     * @param token
     * @TODO 过期时间需要计算
     */
    public void resetRedisUserInfo(String token) {
        String jsonUser = redis.opsForValue().get(token);
        //存在token，已登录
        if (jsonUser != null) {
            User user = JSONObject.parseObject(jsonUser, User.class);
            User userNew = userMapper.selectByPrimaryKey(user.getId());
            redis.opsForValue().set(token, JSON.toJSONString(userNew), 30, TimeUnit.DAYS);
        }
    }


    /**
     * @Description: 获取个人信息
     * @author: ling
     * @date: 2022/5/8
     * @Return: com.ling.module1sbbyyds.interaction.Return.Result
     */
    public ResultVo personalInformation() {
        //  返回token验证后获取的用户对象
        Map<String, Object> userData = UserThreadLocal.get();
        User user = (User) userData.get("user");
        user.setAvatar(ImageUtils.convertImageUrl(user.getAvatar()));
        //去除密码
        user.setPassword(null);

        //返回数据
        UserInfoVo userInfoVo = new UserInfoVo();
        //拷贝
        BeanUtils.copyProperties(user, userInfoVo);

        userInfoVo.setAttNum(45);
        userInfoVo.setFansNum(12);
        userInfoVo.setLikeAndCollectNum(452);

        return ResultVo.success(userInfoVo);
    }

    /**
     * @Description: 获取个人信息  根据id
     * @author: ling
     * @date: 2022/5/8
     * @Return: com.ling.module1sbbyyds.interaction.Return.Result
     */
    public ResultVo personalInformationById(Long userId) {
        //  返回token验证后获取的用户对象
        User user = userMapper.selectByPrimaryKey(userId);
        user.setAvatar(ImageUtils.convertImageUrl(user.getAvatar()));
        //去除密码
        user.setPassword(null);

        //返回数据
        UserInfoVo userInfoVo = new UserInfoVo();
        //拷贝
        BeanUtils.copyProperties(user, userInfoVo);

        userInfoVo.setAttNum(45);
        userInfoVo.setFansNum(12);
        userInfoVo.setLikeAndCollectNum(452);

        return ResultVo.success(userInfoVo);
    }

    /**
     * 修改用户个人信息
     *
     * @param newUser
     * @return
     */
    @Transactional
    public ResultVo updatePersonalInformation(User newUser, HttpServletRequest request) {

        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        Map<String, Object> userData = UserThreadLocal.get();
        User sourceUser = (User) userData.get("user");
        userUpdateWrapper.eq("id", sourceUser.getId());
        //修改用户名
        String userName = newUser.getUserName();
        if (!ObjectUtils.isEmpty(userName)) {
            if (!ObjectUtils.isEmpty(userName.trim())) {
                if (sourceUser.getUserName().equals(newUser.getUserName())) {
                    return ResultVo.fail("不能与原用户名重复！");
                }
                if (newUser.getUserName().length() >= 7) {
                    return ResultVo.fail("长度不能超过是7位！");
                }
                if (getUserNameRepeat(userName)) {
                    return ResultVo.fail("该用户名已被占用！");
                }
            }
            newUser.setUserName(userName);
        }
        if (ObjectUtils.isEmpty(newUser.getBirthday()) || newUser.getBirthday() == "") {
            newUser.setBirthday(null);
        }
        int i = userMapper.updateByPrimaryKeySelective(newUser);
        if (i > 0) {
            resetRedisUserInfo(request.getHeader("AuthorizationOauth_Token"));
            return ResultVo.success(true, "修改成功！");
        }

        return ResultVo.fail("修改失败！");
    }

    /**
     * 判断用户名是否已经存在
     *
     * @param userName 用户名
     * @return
     */
    public boolean getUserNameRepeat(String userName) {
        try {
            Example example = new Example(User.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("userName", userName);
            int count = userMapper.selectCountByExample(example);
            return count > 0;
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
    }

    /**
     * 获取用户个人贴
     *
     * @return
     */
    public ResultVo getPostsList(Integer currentPage, Integer limit) {
        User user = UserThreadLocal.getCurrentUser();
        LambdaQueryWrapper<CommunityPosts> postsQuery = new LambdaQueryWrapper<>();
        postsQuery.eq(CommunityPosts::getUserId, user.getId())
                .orderByDesc(CommunityPosts::getReleaseTime);
        Page<CommunityPosts> communityPostsPage = communityPostsMapper.selectPage(PageUtils.initPage(currentPage, limit), postsQuery);
        // 转换图片地址
        List<CommunityPosts> records = communityPostsPage.getRecords();
        records.forEach(item -> item.setImageList(ImageUtils.convertJsonToImageUrl(item.getImageList())));

        return ResultVo.success(PageUtils.beautifyField(communityPostsPage).setList(records));
    }

    /**
     * 根据用户id 获取用户信息
     *
     * @param id
     * @return
     */
    public ResultVo getOtherUser(String id) {
        User user = userMapper.selectByPrimaryKey(id);
        OtherUser otherUser = new OtherUser();
        BeanUtils.copyProperties(user, otherUser);
        return ResultVo.success(otherUser);
    }

    /**
     * 用户修改密码
     *
     * @param verificationCode 验证码
     * @param newPassword      新密码
     * @return
     */
    public ResultVo changePassword(String verificationCode, String newPassword,
                                   HttpServletRequest request) {
        Map<String, Object> userData = UserThreadLocal.get();
        User user = (User) userData.get("user");
        if (newPassword.isEmpty() || verificationCode.isEmpty()) {
            throw new ApiWarningInfoException("参数不能为空");
        }
        if (!redisDataUtil.verifyCode(verificationCode, user.getPhone())) {
            throw new ApiWarningInfoException("验证码错误");
        }

        User userInfo = new User()
                .setId(user.getId())
                .setPassword(newPassword);
        userMapper.updateByPrimaryKeySelective(userInfo);
        resetRedisUserInfo(request.getHeader("AuthorizationOauth_Token"));
        return ResultVo.success(null, "修改成功！");
    }

    /**
     * 获取用户社区发帖的 所有图片  （图册）
     *
     * @param userId 用户id
     * @return
     */
    public ResultVo getUserImages(String userId) {
        Example example = new Example(CommunityPosts.class);
        Example.Criteria criteria = example.createCriteria();
        example.selectProperties("imageList");
        criteria.andEqualTo("userId", userId);
        criteria.andIsNotNull("imageList");
        List<CommunityPosts> communityPosts = communityPostsMapper.selectByExample(example);
        List<String> images = new ArrayList<>();
        communityPosts.forEach((l) -> {
            List<String> listI = JSONArray.parseArray(l.getImageList(), String.class);
            images.addAll(listI);
        });
        return ResultVo.success(images).put("count", images.size());
    }

    /**
     * 校验验证码是否正确
     *
     * @param phone
     * @param code
     * @return
     */
    public ResultVo checkByCode(String phone, String code) {
        if (phone.isEmpty()) {
            return ResultVo.fail("手机号不能为空！");
        }
        if (code.isEmpty()) {
            return ResultVo.fail("验证码不能为空！");
        }
        if (!validateCode.verifyCode(phone, code)) {
            return ResultVo.fail("验证码错误！");
        }
        redis.opsForValue().set(phone + "updatePassword", "true", 60 * 5);
        return ResultVo.success();
    }

    /**
     * user/updatePassword
     * 修改密码
     *
     * @param phone           手机号
     * @param password        新密码
     * @param confirmPassword 确认密码
     * @return
     */
    public ResultVo updatePassword(String phone, String password, String confirmPassword) {
        if (password.isEmpty() || confirmPassword.isEmpty()) {
            return ResultVo.fail("参数不能为空！");
        }
        if (!password.equals(confirmPassword)) {
            //原密码与旧密码一致
            return ResultVo.fail("新密码输入一致！");
        }
        if (ObjectUtils.isEmpty(redis.opsForValue().get(phone + "updatePassword"))) {
            return ResultVo.fail("短信校验超过五分钟，请返回上一级重新校验！！");
        }
        //修改密码
        Integer count = userMapper.updatePassword(phone, password);
        if (count > 0) {
            return ResultVo.success(null, "修改密码成功！");
        }
        return ResultVo.fail("修改密码失败！");
    }

    /**
     * 获取用户信息  （用户名，头像，id）
     */
    public User getUserInfo(Long userId) {
        return userMapper.selectUserInfo(userId);
    }

}
